{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6e79d5e1",
   "metadata": {},
   "source": [
    "# Fine-Tune Claude-3 Haiku model provided by Amazon Bedrock: End-to-End"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "673651e5",
   "metadata": {},
   "source": [
    "This notebook demonstrates the end-to-end process of fine-tuning the Anthropic Claude-3 Haiku model using Amazon Bedrock, including selecting the base model, configuring hyperparameters, creating and monitoring the fine-tuning job, deploying the fine-tuned model with provisioned throughput and evaluating the performance of the fine-tuned model. \n",
    "\n",
    "You can also do this through the Bedrock Console."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16dd2ad9",
   "metadata": {},
   "source": [
    "## Prerequisites\n",
    "\n",
    " - Make sure you have executed `01_setup.ipynb` notebook.\n",
    " - Make sure you are using the same kernel and instance as `01_setup.ipynb` notebook.\n",
    "\n",
    "<div class=\"alert alert-block alert-warning\">\n",
    "<b>Warning:</b> This notebook will create provisioned throughput for testing the fine-tuned model. Therefore, please make sure to delete the provisioned throughput as mentioned in the last section of the notebook, otherwise you will be charged for it, even if you are not using it.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a3df9fa6",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -qU bert_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec065f85",
   "metadata": {},
   "outputs": [],
   "source": [
    "# restart kernel for packages to take effect\n",
    "from IPython.core.display import HTML\n",
    "HTML(\"<script>Jupyter.notebook.kernel.restart()</script>\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "64d6535c",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Fetching varialbes from `00_Setup&DataPrep_Haiku.ipynb` notebook. \n",
    "%store -r role_arn\n",
    "%store -r s3_train_uri\n",
    "%store -r s3_validation_uri\n",
    "%store -r s3_test_uri\n",
    "%store -r bucket_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cdc353c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pprint\n",
    "pprint.pp(role_arn)\n",
    "pprint.pp(s3_train_uri)\n",
    "pprint.pp(s3_validation_uri)\n",
    "pprint.pp(s3_test_uri)\n",
    "pprint.pp(bucket_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8da055d5",
   "metadata": {},
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b5947ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "import json\n",
    "import os\n",
    "import sys\n",
    "import boto3\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6d7c4a99",
   "metadata": {},
   "outputs": [],
   "source": [
    "session = boto3.session.Session()\n",
    "region = session.region_name\n",
    "sts_client = boto3.client('sts')\n",
    "s3_client = boto3.client('s3')\n",
    "aws_account_id = sts_client.get_caller_identity()[\"Account\"]\n",
    "bedrock = boto3.client(service_name=\"bedrock\")\n",
    "bedrock_runtime = boto3.client(service_name=\"bedrock-runtime\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc15864a",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_file_name = \"test-samsum-10.jsonl\"\n",
    "data_folder = \"haiku-fine-tuning-datasets-samsum\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28042e6e",
   "metadata": {},
   "source": [
    "## Select the model you would like to fine-tune\n",
    "You will have to provide the `base_model_id` for the model you are planning to fine-tune. You can get that using `list_foundation_models` API as follows: \n",
    "```\n",
    "for model in bedrock.list_foundation_models(\n",
    "    byCustomizationType=\"FINE_TUNING\")[\"modelSummaries\"]:\n",
    "    for key, value in model.items():\n",
    "        print(key, \":\", value)\n",
    "    print(\"-----\\n\")\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d0aa8b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "base_model_id = \"anthropic.claude-3-haiku-20240307-v1:0:200k\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f522309",
   "metadata": {},
   "source": [
    "Next you will need to provide the `customization_job_name`, `custom_model_name` and `customization_role` which will be used to create the fine-tuning job. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de385a90",
   "metadata": {},
   "outputs": [],
   "source": [
    "from datetime import datetime\n",
    "ts = datetime.now().strftime(\"%Y-%m-%d-%H-%M-%S\")\n",
    "\n",
    "customization_job_name = f\"model-finetune-job-{ts}\"\n",
    "custom_model_name = f\"finetuned-model-{ts}\"\n",
    "customization_role = role_arn"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "813d939c",
   "metadata": {},
   "source": [
    "## Create fine-tuning job\n",
    "\n",
    "<div class=\"alert alert-block alert-info\">\n",
    "<b>Note:</b> Fine-tuning job will take around 2-4 hrs to complete.</div>\n",
    "\n",
    "Anthropic Claude 3 Haiku fine-tuning in Amazon Bedrock allows customers to define various hyperparameters that can significantly impact the fine-tuning process and the resulting model’s performance. \n",
    "\n",
    "\n",
    "| ***Parameter Name*** | ***Parameter Description*** | ***Type*** | ***Default*** | **Value Range** |\n",
    "| ------- | ------------- | ------ | --------- | ----------- |\n",
    "| epochCount | The maximum number of iterations through the entire training dataset | integer | 2 | 1 - 10 |\n",
    "| batchSize | The number of samples processed before updating model parameters | integer | 32 | 4 - 256 |\n",
    "| learningRateMultiplier | Multiplier that influences the learning rate at which model parameters are updated after each batch | float | 1 | 0.1 - 2 |\n",
    "| earlyStoppingThreshold | The minimum improvement in validation loss required to prevent premature termination of the training process | float | 0.001 | 0-0.1 | \n",
    "| earlyStoppingPatience | The tolerance for stagnation in the validation loss metric before stopping the training process | int | 2 | 1 - 10 |\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b87a1d4c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Select the customization type from \"FINE_TUNING\" or \"CONTINUED_PRE_TRAINING\". \n",
    "customization_type = \"FINE_TUNING\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a9ec356",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define the hyperparameters for fine-tuning Claude-3 Haiku model\n",
    "hyper_parameters = {\n",
    "        \"epochCount\": \"5\",\n",
    "        \"batchSize\": \"32\",\n",
    "        \"learningRateMultiplier\": \"1\",\n",
    "        \"earlyStoppingThreshold\": \"0.001\",\n",
    "        \"earlyStoppingPatience\": \"2\"\n",
    "    }\n",
    "\n",
    "\n",
    "s3_bucket_config=f's3://{bucket_name}/outputs/output-{custom_model_name}'\n",
    "# Specify your data path for training, validation(optional) and output\n",
    "training_data_config = {\"s3Uri\": s3_train_uri}\n",
    "\n",
    "validation_data_config = {\n",
    "        \"validators\": [{\n",
    "            # \"name\": \"validation\",\n",
    "            \"s3Uri\": s3_validation_uri\n",
    "        }]\n",
    "    }\n",
    "\n",
    "output_data_config = {\"s3Uri\": s3_bucket_config}\n",
    "\n",
    "\n",
    "# Create the customization job of fine-tuning Claude model in Amazon Bedrock. This part also starts executing the fine-tuning job underneath in Amzon Bedrock.\n",
    "training_job_response = bedrock.create_model_customization_job(\n",
    "    customizationType=customization_type,\n",
    "    jobName=customization_job_name,\n",
    "    customModelName=custom_model_name,\n",
    "    roleArn=customization_role,\n",
    "    baseModelIdentifier=base_model_id,\n",
    "    hyperParameters=hyper_parameters,\n",
    "    trainingDataConfig=training_data_config,\n",
    "    validationDataConfig=validation_data_config,\n",
    "    outputDataConfig=output_data_config\n",
    ")\n",
    "training_job_response"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea7e58ce",
   "metadata": {},
   "source": [
    "## Check fine-tuning job status\n",
    "\n",
    "You can see the status of the fine-funing job by using the API or by check Bedrock Console --> Foundation Models --> Custom Models --> Jobs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "961f9328",
   "metadata": {},
   "outputs": [],
   "source": [
    "fine_tune_job = bedrock.get_model_customization_job(jobIdentifier=customization_job_name)[\"status\"]\n",
    "print(fine_tune_job)\n",
    "\n",
    "while fine_tune_job == \"InProgress\":\n",
    "    time.sleep(60)\n",
    "    fine_tune_job = bedrock.get_model_customization_job(jobIdentifier=customization_job_name)[\"status\"]\n",
    "    print (fine_tune_job)\n",
    "    time.sleep(60)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4e61c94",
   "metadata": {},
   "outputs": [],
   "source": [
    "fine_tune_job = bedrock.get_model_customization_job(jobIdentifier=customization_job_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a230446",
   "metadata": {},
   "outputs": [],
   "source": [
    "pprint.pp(fine_tune_job)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26ded0a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "output_job_name = \"model-customization-job-\"+fine_tune_job['jobArn'].split('/')[-1]\n",
    "output_job_name"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2349f994",
   "metadata": {},
   "source": [
    "Now we are ready to create [`provisioned throughput`](#) which is needed before you can do the inference on the fine-tuned model.\n",
    "\n",
    "### Overview of Provisioned throughput\n",
    "You specify Provisioned Throughput in Model Units (MU). A model unit delivers a specific throughput level for the specified model. The throughput level of a MU for a given Text model specifies the following:\n",
    "\n",
    "- The total number of input tokens per minute – The number of input tokens that an MU can process across all requests within a span of one minute.\n",
    "\n",
    "- The total number of output tokens per minute – The number of output tokens that an MU can generate across all requests within a span of one minute.\n",
    "\n",
    "Model unit quotas depend on the level of commitment you specify for the Provisioned Throughput.\n",
    "\n",
    "- For custom models with no commitment, a quota of one model unit is available for each Provisioned Throughput. You can create up to two Provisioned Throughputs per account.\n",
    "\n",
    "- For base or custom models with commitment, there is a default quota of 0 model units. To request an increase, use the [limit increase form](#https://support.console.aws.amazon.com/support/home#/case/create?issueType=service-limit-increase)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2e40dad",
   "metadata": {},
   "source": [
    "## Retrieve Custom Model\n",
    "Once the customization job is finished, you can check your existing custom model(s) and retrieve the modelArn of your fine-tuned model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b68db116",
   "metadata": {},
   "outputs": [],
   "source": [
    "# List your custom models\n",
    "bedrock.list_custom_models()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41ba6680",
   "metadata": {},
   "outputs": [],
   "source": [
    "model_id = bedrock.get_custom_model(modelIdentifier=custom_model_name)['modelArn']\n",
    "model_id"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f061dab1",
   "metadata": {},
   "source": [
    "## Create Provisioned Throughput\n",
    "<div class=\"alert alert-block alert-info\">\n",
    "<b>Note:</b> Creating provisioned throughput will take around 20-30mins to complete.</div>\n",
    "\n",
    "You will need to create provisioned throughput to be able to evaluate the model performance. You can do so through the [console].(https://docs.aws.amazon.com/bedrock/latest/userguide/prov-cap-console.html) or use the following api call:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "12eb734a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import boto3 \n",
    "boto3.client(service_name='bedrock')\n",
    "provisioned_model_id = bedrock.create_provisioned_model_throughput(\n",
    " modelUnits=1,\n",
    " provisionedModelName='test-haiku-ft-model', \n",
    " modelId=model_id\n",
    ")['provisionedModelArn']     "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87ce7551",
   "metadata": {},
   "outputs": [],
   "source": [
    "status_provisioning = bedrock.get_provisioned_model_throughput(provisionedModelId = provisioned_model_id)['status']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "10136412",
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "while status_provisioning == 'Creating':\n",
    "    time.sleep(60)\n",
    "    status_provisioning = bedrock.get_provisioned_model_throughput(provisionedModelId=provisioned_model_id)['status']\n",
    "    print(status_provisioning)\n",
    "    time.sleep(60)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5633fe4",
   "metadata": {},
   "source": [
    "## Invoke the Custom Model\n",
    "\n",
    "Before invoking lets get the sample prompt from our test data. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "76399fdc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Provide the prompt text \n",
    "test_file_path = f'{data_folder}/{test_file_name}'\n",
    "with open(test_file_path) as f:\n",
    "    lines = f.read().splitlines()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3a32a85e",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_system_prompt = json.loads(lines[3])['system']\n",
    "test_user_prompt = json.loads(lines[3])['messages'][0]['content']\n",
    "reference_summary = json.loads(lines[3])['messages'][1]['content']\n",
    "pprint.pp(test_system_prompt)\n",
    "pprint.pp(test_user_prompt)\n",
    "pprint.pp(reference_summary)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "31762954",
   "metadata": {},
   "outputs": [],
   "source": [
    "message = [\n",
    "        {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": test_user_prompt\n",
    "        }\n",
    "    ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8799beca",
   "metadata": {},
   "outputs": [],
   "source": [
    "base_model_arn = f'arn:aws:bedrock:{region}::foundation-model/anthropic.claude-3-haiku-20240307-v1:0'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a359e7f5",
   "metadata": {},
   "source": [
    "Make sure to construct model input following the format needed by Anthropic Claude Message API [here](#https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html). \n",
    "Please pay attention to the \"Model invocation request body field\" section in the `body` variable, which we will pass as payload to the custom model trained above. \n",
    "\n",
    "Alternatively, you can also use [Converse API](#https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html) in Amazon Bedrock to invoke model regardless of specific input format the model requires. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5732e431-b66e-4222-bf60-9d98f0749bbe",
   "metadata": {},
   "outputs": [],
   "source": [
    "body=json.dumps(\n",
    "    {\n",
    "        \"anthropic_version\": \"bedrock-2023-05-31\",\n",
    "        \"max_tokens\": 2048,\n",
    "        \"messages\": message,\n",
    "        \"temperature\": 0.1,\n",
    "        \"top_p\": 0.9,\n",
    "        \"system\": test_system_prompt\n",
    "    }  \n",
    ")  \n",
    "\n",
    "fine_tuned_response = bedrock_runtime.invoke_model(body=body, \n",
    "                                        modelId=provisioned_model_id)\n",
    "\n",
    "base_model_response = bedrock_runtime.invoke_model(body=body, \n",
    "                                        modelId=base_model_arn)\n",
    "\n",
    "fine_tuned_response_body = json.loads(fine_tuned_response.get('body').read())\n",
    "base_model_response_body = json.loads(base_model_response.get('body').read())\n",
    "\n",
    "print(\"Base model response: \", base_model_response_body['content'][0]['text'] + '\\n')\n",
    "print(\"Fine tuned model response:\", fine_tuned_response_body['content'][0]['text']+'\\n')\n",
    "print(\"Reference summary from test data: \" , reference_summary)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e4359f44-56ea-46d9-b06c-69b7e9872074",
   "metadata": {},
   "outputs": [],
   "source": [
    "#fine_tuned_response_body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a80d56e-8fa4-4824-975c-3b3b7e9be641",
   "metadata": {},
   "outputs": [],
   "source": [
    "#base_model_response_body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a447b709-6514-4486-aa3a-c3b26695e0a6",
   "metadata": {},
   "outputs": [],
   "source": [
    "#print(\"Fine tuned model response:\", fine_tuned_response_body['content'][0]['text']+'\\n')\n",
    "\n",
    "# print(\"Base model response: \", base_model_response_body['content'][0]['text'] + '\\n')\n",
    "# print(\"Fine tuned model response:\", fine_tuned_response_body['content'][0]['text']+'\\n')\n",
    "# print(\"Reference summary from test data: \" , reference_summary)\n",
    "\n",
    "\n",
    "#print(\"Fine tuned model response:\", fine_tuned_response_body['content'][0]['text']+'\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0bb701d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# body=json.dumps(\n",
    "#     {\n",
    "#         \"anthropic_version\": \"bedrock-2023-05-31\",\n",
    "#         \"max_tokens\": 2048,\n",
    "#         \"messages\": message,\n",
    "#         \"temperature\": 0.1,\n",
    "#         \"top_p\": 0.9,\n",
    "#         \"system\": test_system_prompt\n",
    "#     }  \n",
    "# )  \n",
    "\n",
    "# fine_tuned_response = bedrock_runtime.invoke_model(body=body, \n",
    "#                                         modelId=provisioned_model_id)\n",
    "\n",
    "# base_model_response = bedrock_runtime.invoke_model(body=body, \n",
    "#                                         modelId=base_model_arn)\n",
    "\n",
    "# fine_tuned_response_body = json.loads(fine_tuned_response.get('body').read())\n",
    "# base_model_response_body = json.loads(base_model_response.get('body').read())\n",
    "\n",
    "# print(\"Base model response: \", base_model_response_body[\"results\"][0][\"outputText\"] + '\\n')\n",
    "# print(\"Fine tuned model response:\", fine_tuned_response_body[\"results\"][0][\"outputText\"]+'\\n')\n",
    "# print(\"Reference summary from test data: \" , reference_summary)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eaf7f137",
   "metadata": {},
   "source": [
    "## Evaluate the performance of the model \n",
    "In this section, we will use `BertScore` metrics  to evaluate the performance of the fine-tuned model as compared to base model to check if fine-tuning has improved the results.\n",
    "\n",
    "- `BERTScore`: calculates the similarity between a summary and reference texts based on the outputs of BERT (Bidirectional Encoder Representations from Transformers), a powerful language model. [Medium article link](#https://haticeozbolat17.medium.com/bertscore-and-rouge-two-metrics-for-evaluating-text-summarization-systems-6337b1d98917)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ed89437",
   "metadata": {},
   "outputs": [],
   "source": [
    "base_model_generated_response = [base_model_response_body['content'][0]['text']]\n",
    "fine_tuned_generated_response = [fine_tuned_response_body['content'][0]['text']]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d1bce422",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bert_score import score\n",
    "reference_summary = [reference_summary]\n",
    "fine_tuned_model_P, fine_tuned_R, fine_tuned_F1 = score(fine_tuned_generated_response, reference_summary, lang=\"en\")\n",
    "base_model_P, base_model_R, base_model_F1 = score(base_model_generated_response, reference_summary, lang=\"en\")\n",
    "print(\"F1 score: base model \", base_model_F1)\n",
    "print(\"F1 score: fine-tuned model\", fine_tuned_F1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0625b4e8",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "From the scores above and looking at the base model summary, fine-tuned model summary and reference summary, it clearly indicates that fine-tuning the model tends to improve the results on the task its trained on. We only used 1K records for training with 100 validation records and 2 epochs, and were able to get better results. \n",
    "\n",
    "<div class=\"alert alert-block alert-info\">\n",
    "<b>Tip:</b> \n",
    "    Please refer to the <a href=\"https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-guidelines.html\" style=\"color: #3372FF\">guidelines </a> provided for fine-tuning the model based on your task. </div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44b05602",
   "metadata": {},
   "source": [
    "## Delete provisioned througput\n",
    "<div class=\"alert alert-block alert-warning\">\n",
    "<b>Warning:</b> Please make sure to delete providsioned throughput as there will cost incurred if its left in running state, even if you are not using it. \n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7b9491a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "bedrock.delete_provisioned_model_throughput(provisionedModelId=provisioned_model_id)"
   ]
  }
 ],
 "metadata": {
  "availableInstances": [
   {
    "_defaultOrder": 0,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.t3.medium",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 1,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.t3.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 2,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.t3.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 3,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.t3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 4,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 5,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 6,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 7,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 8,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 9,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 10,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 11,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 12,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5d.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 13,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5d.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 14,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5d.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 15,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5d.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 16,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5d.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 17,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5d.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 18,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5d.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 19,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 20,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": true,
    "memoryGiB": 0,
    "name": "ml.geospatial.interactive",
    "supportedImageNames": [
     "sagemaker-geospatial-v1-0"
    ],
    "vcpuNum": 0
   },
   {
    "_defaultOrder": 21,
    "_isFastLaunch": true,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.c5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 22,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.c5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 23,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.c5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 24,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.c5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 25,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 72,
    "name": "ml.c5.9xlarge",
    "vcpuNum": 36
   },
   {
    "_defaultOrder": 26,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 96,
    "name": "ml.c5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 27,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 144,
    "name": "ml.c5.18xlarge",
    "vcpuNum": 72
   },
   {
    "_defaultOrder": 28,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.c5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 29,
    "_isFastLaunch": true,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g4dn.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 30,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g4dn.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 31,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g4dn.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 32,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g4dn.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 33,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g4dn.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 34,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g4dn.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 35,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 61,
    "name": "ml.p3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 36,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 244,
    "name": "ml.p3.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 37,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 488,
    "name": "ml.p3.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 38,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.p3dn.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 39,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.r5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 40,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.r5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 41,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.r5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 42,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.r5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 43,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.r5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 44,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.r5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 45,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.r5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 46,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.r5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 47,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 48,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 49,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 50,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 51,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 52,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 53,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.g5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 54,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.g5.48xlarge",
    "vcpuNum": 192
   },
   {
    "_defaultOrder": 55,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 56,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4de.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 57,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.trn1.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 58,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1.32xlarge",
    "vcpuNum": 128
   },
   {
    "_defaultOrder": 59,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1n.32xlarge",
    "vcpuNum": 128
   }
  ],
  "instance_type": "ml.t3.medium",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
